package edu.cn.nlsde.tmfst.mlda;

public class AliasLDA {

//    public int K;
//    public int M;
//    public int V;
//
//    public int MH_STEPS = 2;
//
//    public double alpha;
//    public double beta;
//
//    public double Vbeta;
//
//    public int nwk[][];
//    public int nk[];
//
//    public TIntIntHashMap[] ndk;
//
//    public int niters;
//
//    public List<voseAlias> q = new ArrayList<voseAlias>();
//
//    public int[][] z_assigns;
//
//    public double[] p;
//
//    public List<List<Integer>> docs = new ArrayList<List<Integer>>();
//    public HashMap<String, Integer> w2i = new HashMap<String, Integer>();
//    public HashMap<Integer, String> i2w = new HashMap<Integer, String>();
//    public String path;
//    private String outputPath = null;
//
//    public void loadTxts() {
//        String txtPath = this.path;
//        BufferedReader reader = IOUtil.getReader(txtPath, "UTF-8");
//
//        String line;
//        try {
//            line = reader.readLine();
//            while (line != null) {
//                List<Integer> doc = new ArrayList<Integer>();
//
//                String[] tokens = line.trim().split("\\s+");
//                for (String token : tokens) {
//                    if (!w2i.containsKey(token)) {
//                        w2i.put(token, w2i.size());
//                        i2w.put(w2i.get(token), token);
//                    }
//                    doc.add(w2i.get(token));
//                }
//                docs.add(doc);
//                line = reader.readLine();
//            }
//            reader.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//        M = docs.size();
//        V = w2i.size();
//        return;
//    }
//
//    public void setParameters(double alpha, double beta, int ntopics, int niters) {
//        K = ntopics;
//        this.alpha = alpha;
//        this.beta = beta;
//        this.niters = niters;
//    }
//
//    public void init_model() {
//        Vbeta = V * beta;
//
//        p = new double[K];
//
//        nwk = new int[V][K];
//        nk = new int[K];
//
//        ndk = new TIntIntHashMap[M];
//        z_assigns = new int[M][];
//
//        for (int m = 0; m != M; m++) {
//            ndk[m] = new TIntIntHashMap();
//            int N = docs.get(m).size();
//            z_assigns[m] = new int[N];
//            for (int n = 0; n != N; n++) {
//                int w = docs.get(m).get(n);
//                int z = (int) Math.floor(Math.random() * K);
//
//                nwk[w][z]++;
//                nk[z]++;
//
//                ndk[m].adjustOrPutValue(z, 1, 1);
//
//                z_assigns[m][n] = z;
//            }
//        }
//
//        this.specific_init();
//    }
//
//    public void specific_init() {
//        System.out.println("Initializing the alias tables ...");
//        for (int w = 0; w != V; w++) {
//            q.add(new voseAlias());
//        }
//        for (int w = 0; w < V; ++w) {
//            q.get(w).init(K);
//            generateQtable(w);
//        }
//    }
//
//    public void generateQtable(int w) {
//        {
//            q.get(w).wsum = 0.0;
//            for (int k = 0; k < K; ++k) {
//                q.get(w).w[k] = (nwk[w][k] + beta) / (nk[k] + Vbeta);
//                q.get(w).wsum += q.get(w).w[k];
//            }
//            q.get(w).constructTable();
//        }
//    }
//
//    public void sample_doc(int m) {
//        int N = docs.get(m).size();
//
//        for (int n = 0; n != N; n++) {
//            int w = docs.get(m).get(n);
//
//            // remove z_ij from the count variables
//            int topic = z_assigns[m][n];
//            int new_topic = -1;
////			int old_topic = topic;
//
//            p = new double[ndk[m].keys().length];
//
//            nwk[w][topic]--;
//            nk[topic]--;
//
//            if (ndk[m].get(topic) == 0) {
//                ndk[m].remove(topic);
//            } else {
//                ndk[m].adjustValue(topic, -1);
//            }
//
//			/* Travese all non-zero document-topic distribution */
//            double psum = 0.0;
//            int index = 0;
//            for (int k : ndk[m].keys()) {
//                psum += ndk[m].get(k) *
//                        (nwk[w][k] + beta) / (nk[k] + Vbeta);
//                p[index] = psum;
//                index++;
//            }
//
//            double select_pr = psum / (psum + alpha * q.get(w).wsum);
//
//            //MHV to draw new topic
//            for (int s = 0; s < MH_STEPS; s++) {
//                //1. Flip a coin
//                if (Math.random() < select_pr) {
//                    double u = Math.random() * psum;
//                    for (int i = 0; i != index; i++) {
//                        if (u < p[i]) {
//                            new_topic = ndk[m].keys()[i];
//                            break;
//                        }
//                    }
//                } else {
//                    q.get(w).noSamples++;
//                    if (q.get(w).noSamples > (K / 2.0)) {
//                        generateQtable(w);
//                    }
//                    new_topic = q.get(w).sample(Math.random(), Math.random());
//                } // if else
//
//                if (topic != new_topic) {
//                    //2. Find acceptance probability
//                    double temp_old = (nwk[w][topic] + beta) / (nk[topic] + Vbeta);
//                    double temp_new = (nwk[w][new_topic] + beta) / (nk[new_topic] + Vbeta);
//                    double acceptance = (ndk[m].get(new_topic) + alpha) / (ndk[m].get(topic) + alpha)
//                            * temp_new / temp_old
//                            * (ndk[m].get(topic) * temp_old + alpha * q.get(w).w[topic])
//                            / (ndk[m].get(new_topic) * temp_new + alpha * q.get(w).w[new_topic]);
//                    if (Math.random() < acceptance) {
//                        topic = new_topic;
//                    }
//                }
//            } // for
//            nwk[w][topic]++;
//            nk[topic]++;
//
//            ndk[m].adjustOrPutValue(topic, 1, 1);
//            z_assigns[m][n] = topic;
//        }
//    }
//
//    public void estimate() {
//        for (int iter = 0; iter != niters; iter++) {
//            System.out.println("Alias LDA Interation " + iter + " ...");
//            if (iter % 30000 == 0) {
//                this.save_theta(iter);
//            }
//
//            long begin = System.currentTimeMillis();
//            for (int m = 0; m != M; m++)
//                this.sample_doc(m);
//            System.out.println((System.currentTimeMillis() - begin) / 1000.0);
//        }
//    }
//
//    public double[][] computePhi() {
//        double[][] phi = new double[K][V];
//        for (int k = 0; k != K; k++) {
//            for (int v = 0; v != V; v++) {
//                phi[k][v] = (nwk[v][k] + beta) / (nk[k] + Vbeta);
//            }
//        }
//        return phi;
//    }
//
//    public ArrayList<List<Entry<String, Double>>> sortedTopicWords(
//            double[][] phi, int T) {
//        ArrayList<List<Entry<String, Double>>> res = new ArrayList<List<Entry<String, Double>>>();
//        for (int k = 0; k != T; k++) {
//            HashMap<String, Double> term2weight = new HashMap<String, Double>();
//            for (String term : w2i.keySet())
//                term2weight.put(term, phi[k][w2i.get(term)]);
//
//            List<Entry<String, Double>> pairs = new ArrayList<Entry<String, Double>>(
//                    term2weight.entrySet());
//            Collections.sort(pairs, new Comparator<Entry<String, Double>>() {
//                public int compare(Entry<String, Double> o1,
//                                   Entry<String, Double> o2) {
//                    return (o2.getValue().compareTo(o1.getValue()));
//                }
//            });
//
//            res.add(pairs);
//        }
//
//        return res;
//    }
//
//    public void printTopics(int top_n) {
//        double[][] phi = computePhi();
//        ArrayList<List<Entry<String, Double>>> pairsList = this
//                .sortedTopicWords(phi, K);
//        for (int k = 0; k != K; k++) {
//            System.out.println("Topic " + k + ":");
//            for (int i = 0; i != top_n; i++) {
//                System.out.println(pairsList.get(k).get(i).getKey() + " "
//                        + pairsList.get(k).get(i).getValue());
//            }
//        }
//    }
//
////    private void save_tassign(int iterNum) {
////        String outputPath = (new File(this.path)).getParentFile().getAbsolutePath()+"/model-"+iterNum+".tassign";
////        BufferedWriter writer =  IOUtil.getWriter(outputPath);
////        try {
////            for(int docIndex=0;docIndex<this.z_assigns.length;docIndex++){
////                for(int wordIndex=0;wordIndex<z_assigns[docIndex].length;wordIndex++){
////
////                }
////            }
////            writer.close();
////        } catch (IOException e) {
////            e.printStackTrace();
////        }
////
////    }
//
//    private void save_theta(int iterNum) {
//        String outputPath = this.outputPath + "model-" + iterNum + ".theta";
//        BufferedWriter writer = IOUtil.getWriter(outputPath);
//
//        try {
//            for (int docIndex = 0; docIndex < docs.size(); docIndex++) {
//                for (int topicId = 0; topicId < this.K; topicId++) {
//                    double pk = this.alpha;
//                    if (this.ndk[docIndex].containsKey(topicId)) {
//                        pk += this.ndk[docIndex].get(topicId);
//                    }
//                    writer.write((pk) / (this.docs.get(docIndex).size() + this.K * this.alpha) + " ");
//                }
//                writer.write("\n");
//            }
//
//            writer.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//    }
//
//    public static void main(String args[]) throws IOException {
//        AliasLDA lda = new AliasLDA();
//        String root = "data/news/wntm-NoReweight/";
//        lda.path = root + "news.adjacent";
//        lda.outputPath = root + "AliasLDA/";
//        (new File(lda.outputPath)).mkdirs();
//        lda.loadTxts();//
//        lda.setParameters(0.1, 0.01, 100, 2000);
//        lda.init_model();
//        lda.estimate();
//        lda.printTopics(10);
//        lda.save_theta(2000);
//    }


}
